
import os
import tkinter as tk
from tkinter import filedialog, messagebox
import pandas as pd
from pathlib import Path

class XlsCsvToTsConverter:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("XLS/CSV转TS转换器")
        self.root.geometry("650x350")
        self.setup_ui()
    
    def setup_ui(self):
        # 主框架
        main_frame = tk.Frame(self.root, padx=20)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 转换选项
        option_frame = tk.Frame(main_frame)
        option_frame.pack(fill=tk.X, pady=5)
        tk.Label(option_frame, text="转换模式:", font=("Arial", 9, "bold")).pack(anchor="w")
        
        self.convert_type = tk.StringVar(value="folder")
        tk.Radiobutton(option_frame, text="批量转换文件夹", 
                      variable=self.convert_type, value="folder").pack(side=tk.LEFT)
        tk.Radiobutton(option_frame, text="转换单个文件", 
                      variable=self.convert_type, value="file").pack(side=tk.LEFT)
        
        # 输入路径
        input_frame = tk.Frame(main_frame)
        input_frame.pack(fill=tk.X, pady=5)
        tk.Label(input_frame, text="输入路径:").pack(anchor="w")
        self.input_entry = tk.Entry(input_frame)
        self.input_entry.pack(fill=tk.X, padx=5)
        tk.Button(input_frame, text="浏览...", command=self.select_input).pack(pady=5)
        
        # 输出路径
        output_frame = tk.Frame(main_frame)
        output_frame.pack(fill=tk.X, pady=5)
        tk.Label(output_frame, text="输出路径:").pack(anchor="w")
        self.output_entry = tk.Entry(output_frame)
        self.output_entry.pack(fill=tk.X, padx=5)
        tk.Button(output_frame, text="浏览...", command=self.select_output).pack(pady=5)
        
        # 类型生成选项
        type_frame = tk.Frame(main_frame)
        type_frame.pack(fill=tk.X, pady=5)
        tk.Label(type_frame, text="类型生成:", font=("Arial", 9, "bold")).pack(anchor="w")
        
        self.type_options = tk.StringVar(value="interface")
        tk.Radiobutton(type_frame, text="生成Interface", 
                      variable=self.type_options, value="interface").pack(side=tk.LEFT)
        tk.Radiobutton(type_frame, text="生成Type", 
                      variable=self.type_options, value="type").pack(side=tk.LEFT)
        
        # 转换按钮
        tk.Button(main_frame, text="开始转换", command=self.convert).pack(pady=10)
    
    def select_input(self):
        if self.convert_type.get() == "folder":
            path = filedialog.askdirectory(title="选择输入文件夹")
        else:
            path = filedialog.askopenfilename(title="选择文件", 
                filetypes=[("Excel/CSV", "*.xls *.xlsx *.csv")])
        if path:
            self.input_entry.delete(0, tk.END)
            self.input_entry.insert(0, path)
    
    def select_output(self):
        path = filedialog.askdirectory(title="选择输出文件夹")
        if path:
            self.output_entry.delete(0, tk.END)
            self.output_entry.insert(0, path)
    
    def convert(self):
        input_path = self.input_entry.get()
        output_path = self.output_entry.get()
        
        if not all([input_path, output_path]):
            messagebox.showerror("错误", "请选择输入和输出路径")
            return
        
        try:
            files = []
            if self.convert_type.get() == "folder":
                for ext in ('*.xls', '*.xlsx', '*.csv'):
                    files.extend(Path(input_path).glob(ext))
            else:
                files.append(Path(input_path))
            
            for file in files:
                self.process_file(file, output_path)
            
            messagebox.showinfo("完成", f"成功转换 {len(files)} 个文件")
        except Exception as e:
            messagebox.showerror("错误", f"转换失败: {str(e)}")
    
    def process_file(self, file_path, output_dir):
        # 读取数据
        if file_path.suffix == '.csv':
            df = pd.read_csv(file_path, header=None, skiprows=2)
            comments = pd.read_csv(file_path, header=None, nrows=2)
        else:
            df = pd.read_excel(file_path, header=None, skiprows=2)
            comments = pd.read_excel(file_path, header=None, nrows=2)
        
        # 生成TS内容
        ts_content = self.generate_ts(df, comments, file_path.stem)
        
        # 写入文件
        output_path = Path(output_dir) / f"{file_path.stem}.ts"
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(ts_content)
    
    def generate_ts(self, df, comments, name):
        headers = df.iloc[0].tolist()
        rows = []
        
        # 生成类型定义
        type_def = []
        for i, header in enumerate(headers):
            if pd.isna(header):
                continue
            col_type = self.infer_column_type(df, i)
            type_def.append(f"  {header}: {col_type};")
        
        # 生成数据行
        for i in range(1, len(df)):
            row = df.iloc[i]
            if pd.isna(row[0]):
                continue
            row_data = []
            for j in range(len(headers)):
                if j >= len(row) or pd.isna(row[j]):
                    continue
                val = self.format_ts_value(row[j])
                row_data.append(f"{headers[j]}: {val}")
            rows.append(f"  {{ {', '.join(row_data)} }},")
        
        # 组合TS内容
        ts_content = "// 自动生成的TypeScript类型定义\n"
        ts_content += f"// 源文件: {name}\n"
        
        # 添加注释
        for _, comment in comments.iterrows():
            ts_content += f"// {comment[0]}\n"
        
        # 添加类型定义
        if self.type_options.get() == "interface":
            ts_content += f"\nexport interface I{name.capitalize()} {{\n" + "\n".join(type_def) + "\n}\n\n"
        else:
            ts_content += f"\nexport type T{name.capitalize()} = {{\n" + "\n".join(type_def) + "\n};\n\n"
        
        # 添加数据
        ts_content += f"export const {name}Data: {'I' if self.type_options.get() == 'interface' else 'T'}{name.capitalize()}[] = [\n"
        ts_content += "\n".join(rows) + "\n];"
        
        return ts_content
    
    def infer_column_type(self, df, col_idx):
        types = set()
        for i in range(1, len(df)):
            val = df.iloc[i, col_idx]
            if pd.isna(val):
                continue
            if isinstance(val, (int, float)):
                types.add("number")
            elif isinstance(val, bool):
                types.add("boolean")
            else:
                types.add("string")
        
        if len(types) == 0:
            return "any"
        elif len(types) == 1:
            return types.pop()
        else:
            return " | ".join(sorted(types))
    
    def format_ts_value(self, value):
        if pd.isna(value):
            return "null"
        if isinstance(value, bool):
            return "true" if value else "false"
        if isinstance(value, (int, float)):
            return str(value)
        return f'"{str(value).replace('"', '\\"')}"'

if __name__ == "__main__":
    app = XlsCsvToTsConverter()
    app.root.mainloop()
